#include <assert.h>
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>

/**
 * @brief 介绍原子操作
 */
void testAtomic()
{
    std::atomic<int> anVar{10};
    anVar.store(42, std::memory_order_relaxed); // 原子储存
    auto nVar = anVar.load(std::memory_order_relaxed); // 原子加载
    std::cout << "Value" << nVar << std::endl;

    anVar.fetch_add(1, std::memory_order_relaxed); // 原子加法
    nVar = anVar.load(std::memory_order_relaxed); // 原子加载
    std::cout << "Value" << nVar << std::endl;

    std::atomic<bool> abFlag{false};
    std::atomic<int> anValue{10};
    std::atomic<int*> anpValue{nullptr}; // 基本原子类型

    anVar.store(42); // 储存值
    nVar = anVar.load(); // 加载值

    // 读-修改-写操作
    auto nOdd = anVar.fetch_add(5); // 原子加，返回旧值
    nOdd = anVar.fetch_sub(3); // 原子减
    anVar.fetch_and(0xFFFF); // 原子与
    anVar.fetch_or(0xFFFF); // 原子或

    ++anValue; // 对于整数类型有额外操作
    anValue += 5;

    ++anpValue; //原子指针算数
}

/**
 * @brief 介绍改动序列
 */
void testModificationOrder()
{
    std::atomic<int> anVar{0};

    auto f1 = [&anVar]()
    {
        anVar.store(1, std::memory_order_relaxed);
        anVar.store(2, std::memory_order_relaxed);
    };
    auto f2 = [&anVar]()
    {
        anVar.store(2, std::memory_order_relaxed);
    };


    std::jthread t1{f1};
    std::jthread t2{f2};

    std::cout << "Final value of var: " << anVar.load(std::memory_order_relaxed);
}

/**
 * @brief 自旋锁
 */
class SpinLock
{
public:
    void lock()
    {
        // 使用acquire内存序。确保临界区的读写不会重排到lock之前
        while (_abLocked.exchange(true, std::memory_order_acquire))
        {
            // 自旋等待，直到锁可用
        }
    }

    void unlock()
    {
        // 使用release内存序，确保临界区内的读写不会重排到unlo之后
        _abLocked.store(false, std::memory_order_release);
    }

private:
    std::atomic<bool> _abLocked{false};
};

/**
 * @brief 宽松内存序
 */
void testRelaxed()
{
    std::atomic<int> anVar1{0}, anVar2{0};

    auto func1 = [&]()
    {
        anVar1.store(1, std::memory_order_relaxed);
        anVar2.store(1, std::memory_order_relaxed);
    };
    auto func2 = [&]()
    {
        if (anVar2.load(std::memory_order_relaxed) == 1)
        {
            assert(anVar1.load(std::memory_order_relaxed) == 1); // 可能会失败
        }
    };

    std::jthread t1{func1};
    std::jthread t2{func2};
}

/**
 * @brief 消费模型
 */
class DataProducerConsumer
{
public:
    // 构造函数
    DataProducerConsumer() : data_ptr(nullptr)
    {
    }

    // 启动生产者和消费者线程
    void start()
    {
        // 使用 std::jthread 启动生产者和消费者线程
        producer_thread = std::jthread(&DataProducerConsumer::producer, this);
        consumer_thread = std::jthread(&DataProducerConsumer::consumer, this);

        // 等待一段时间以确保生产者和消费者线程完成
        std::this_thread::sleep_for(std::chrono::seconds(5));
    }

private:
    // 定义 Data 结构体
    struct Data
    {
        int value;
        const char* message;
    };

    // 生产者函数
    void producer()
    {
        Data* p = new Data{42, "Hello World"};
        // 发布数据，使用 release 确保数据在指针之前准备好
        data_ptr.store(p, std::memory_order_release);
    }

    // 消费者函数
    void consumer()
    {
        Data* p;
        // 消费指针，使用 consume 建立依赖关系
        while (!(p = data_ptr.load(std::memory_order_consume)))
        {
            // 自旋等待
        }
        // 这些访问依赖于 p，保证能看到 producer 中在 store 之前的值
        assert(p->value == 42); // 有数据依赖，保证正确
        assert(p->message[0] == 'H'); // 有数据依赖，保证正确
    }

    std::atomic<Data*> data_ptr; // 原子指针
    std::jthread producer_thread; // 生产者线程
    std::jthread consumer_thread; // 消费者线程
};

/**
 * @brief 获取 - 释放模型
 */
class AcquireRelease
{
public:
    void producer()
    {
        _nData = 42; // 非原子数据写入
        _abFlag.store(true , std::memory_order_release); // 释放操作，确保前面的所有操作在存储之前完成
    }

    void consumer()
    {
        // 获取操作：等待标志位，并建立同步关系
        while (!_abFlag.load(std::memory_order_acquire))
        { // 自旋等待
        }
        // 这里确保 producer 中在 release 之前所有写操作
        assert(_nData == 42);
    }

    void start()
    {
        std::jthread t1(&AcquireRelease::producer, this);
        std::jthread t2(&AcquireRelease::consumer, this);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

private:
    int _nData{};
    std::atomic<bool> _abFlag{false};
};

class AcqRel
{
public:
    void increment_counter()
    {
        // 读-修改-写操作，同时需要获取和释放语义
        int nOdd = _anCounter.fetch_add(1 , std::memory_order_acq_rel);
        // 这里既要看见之前的修改，也能保证当前修改对后续操作可见
    }

    int get_value() const
    {
        // 只需要获取语义，看到最新的值
        return _anCounter.load(std::memory_order_acquire);
    }

    void start()
    {
        std::vector<std::thread> threads;
        for (int i = 0; i < 10; ++i)
        {
            threads.emplace_back(&AcqRel::increment_counter, this);
        }

        // 等待所有线程完成
        for (auto& t : threads)
        {
            t.join();
        }

        assert(get_value() == 10); // 保证成功
    }
private:
    std::atomic<int> _anCounter{};
};

/**
 * @brief 顺序一致性模型
 */
class SequentialConsistencyExample
{
public:
    void writer1()
    {
        _anX.store(1, std::memory_order_seq_cst); // 操作 A
    }

    void writer2()
    {
        _anY.store(1, std::memory_order_seq_cst); // 操作 B
    }

    void reader1()
    {
        if (_anX.load(std::memory_order_seq_cst) == 1) // 操作 C
        {
            _anZ1.fetch_add(1, std::memory_order_relaxed);
        }
        if (_anY.load(std::memory_order_seq_cst) == 1) // 操作 D
        {
            _anZ1.fetch_add(1, std::memory_order_relaxed);
        }
    }

    void reader2()
    {
        if (_anY.load(std::memory_order_seq_cst) == 1) // 操作 E
        {
            _anZ2.fetch_add(1, std::memory_order_relaxed);
        }
        if (_anX.load(std::memory_order_seq_cst) == 1) // 操作 F
        {
            _anZ2.fetch_add(1, std::memory_order_relaxed);
        }
    }

    void start()
    {
        std::jthread t1(&SequentialConsistencyExample::writer1, this);
        std::jthread t2(&SequentialConsistencyExample::writer2, this);
        std::jthread t3(&SequentialConsistencyExample::reader1, this);
        std::jthread t4(&SequentialConsistencyExample::reader2, this);

        t1.join();
        t2.join();
        t3.join();
        t4.join();

        assert(_anZ1.load() + _anZ2.load() >= 1); // 使用 seq_cst 时永远不会失败
    }

private:
    std::atomic<int> _anX{0}, _anY{0};
    std::atomic<int> _anZ1{0}, _anZ2{0};
};

int main()
{
    // testAtomic();
    // testModificationOrder();
    // testRelaxed();
    // DataProducerConsumer dpc;
    // 启动生产者和消费者线程
    // dpc.start();


    return 0;
}
